﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NetworkSimulator
{
    public class OfflinePhase_RRATE
    {
        protected IEList ieList = IEList.instance();
        protected Topology map = Topology.instance();

        //Quantity of shortest Paths
        public int k;

        //to contain k shortest paths
        public List<List<Path>> kShortestPaths = new List<List<Path>>();

        //to contain x value
        public List<List<int>> xlist = new List<List<int>>();

        //threshold
        //public int Ncount;
        public int N;




        public static OfflinePhase_RRATE singletonOfflineRRATE;

        public OfflinePhase_RRATE()
        {
            k = 5;
            N = 2;
            OfflinePhase();
        }

        // Synchronize object
        public static object lockingObject = new object();


        public static OfflinePhase_RRATE instance()
        {
            if (singletonOfflineRRATE == null)
            {
                lock (lockingObject)
                {
                    if (singletonOfflineRRATE == null)
                        singletonOfflineRRATE = new OfflinePhase_RRATE();
                }
            }
            return singletonOfflineRRATE;
        }


        public Link getLink(int s, int d)
        {
            foreach (var node in map.Nodes)
                if (node.Id == s)
                    foreach (var link in node.Links)
                    {
                        if (d == link.Destination.Id)
                        {
                            return link;
                        }
                    }
            return null;
        }

        public void OfflinePhase()
        {
            //initialize slist, dlist, wlist
            List<int> slist = new List<int>();
            List<int> dlist = new List<int>();
            List<double> wlist = new List<double>();

            //set input of Yen's algorithm
            foreach (var node in map.Nodes)
                foreach (var link in node.Links)
                {
                    slist.Add(link.Source.Id);
                    dlist.Add(link.Destination.Id);
                    wlist.Add(link.ResidualBandwidth);
                }


            YenAlgorithm.YenAlgorithm yen = new YenAlgorithm.YenAlgorithm(map.Nodes.Count(), slist, dlist, wlist);

            foreach (var pair in ieList.IngressEgressList)
            {

                //to convert double list to path list
                List<Path> kpathtmp = new List<Path>();

                //Find k shortest paths, calculate value
                List<List<double>> tmp = new List<List<double>>();
                tmp = yen.getKShortestPaths(pair.Ingress.Id, pair.Egress.Id, k);

                List<int> x = new List<int>();

                //Go to each path of k paths
                foreach (var path in tmp)
                {

                    Path pathtmp = new Path();

                    //Go to each node id of path to convert
                    for (int i = 0; i < path.Count - 2; i++)
                    {
                        //Create link of path
                        Link linktmp = new Link(getLink((int)path[i], (int)path[i + 1]));
                        pathtmp.Add(linktmp);
                    }

                    //Initialize x reward
                    x.Add(0);

                    //Add to k-path list
                    kpathtmp.Add(pathtmp);
                }

                xlist.Add(x);
                kShortestPaths.Add(kpathtmp);
            }
        }

    }
}
